package system

import (
	"fmt"
	"runtime"
	"strings"

	"gitee.com/liumou_site/gf"

	"gitee.com/liumou_site/gcs"
	"gitee.com/liumou_site/logger"
)

// osArch 根据传入的 OsInfo 对象的架构信息，设置其对应的架构标志位。
// 参数:
//
//	info - 指向 OsInfo 结构体的指针，包含操作系统相关信息。
//	      该结构体应至少包含以下字段：
//	      - Arch: 字符串类型，表示当前系统的架构名称。
//	      - IsArm64: 布尔类型，标记是否为 ARM64 架构。
//	      - IsMips: 布尔类型，标记是否为 MIPS 架构。
//	      - IsAmd64: 布尔类型，标记是否为 AMD64 架构。
//
// 返回值:
//
//	无返回值，但会直接修改传入的 OsInfo 对象的字段值。
func osArch(info *OsInfo) {
	// 如果架构为 "arm64" 或 "aarch64"，设置 IsArm64 为 true。
	if strings.EqualFold(info.Arch, "arm64") || strings.EqualFold(info.Arch, "aarch64") {
		info.IsArm64 = true
		return
	}

	// 如果架构为 "mips64le" 或 "mips64"，设置 IsMips 为 true。
	if strings.EqualFold(info.Arch, "mips64le") || strings.EqualFold(info.Arch, "mips64") {
		info.IsMips = true
		return
	}

	// 如果架构为 "amd64" 或 "x86_64"，设置 IsAmd64 为 true。
	if strings.EqualFold(info.Arch, "amd64") || strings.EqualFold(info.Arch, "x86_64") {
		info.IsAmd64 = true
	}
}

// GetOsInfo 获取操作系统信息并返回一个包含详细信息的 OsInfo 结构体指针。
// 参数: 无
// 返回值:
//   - info: 指向 OsInfo 结构体的指针，包含操作系统的名称、版本、架构等信息。
//   - err: 错误信息，如果在获取系统信息过程中发生错误，则返回具体的错误描述。
func GetOsInfo() (info *OsInfo, err error) {
	// 初始化OsInfo实例
	info = new(OsInfo)
	// 初始化架构标识为false
	info.IsMips = false
	info.IsArm64 = false
	info.IsAmd64 = false

	// 创建Shell命令执行实例
	gc := gcs.NewShell()

	// 获取操作系统类型和架构
	osType := runtime.GOOS
	info.Arch = runtime.GOARCH
	info.Version = "10"

	// 根据架构设置OsInfo属性
	osArch(info)

	// 当操作系统为Linux时，进一步获取系统信息
	if strings.EqualFold(osType, "linux") {
		// 获取Linux发行版名称
		gc.RunShell("grep ^ID /etc/os-release")
		text := gc.Strings
		osType = strings.Split(text, "=")[1]
		osType = strings.Fields(osType)[0] // 去除换行符、空格等多余字符
		info.Name = osType

		// 检查执行命令过程中是否有错误
		if gc.Err != nil {
			return info, fmt.Errorf("查询系统发行版失败")
		}

		// 根据不同的Linux发行版，获取对应的版本信息
		switch strings.ToLower(osType) {
		case strings.ToLower("kylin"):
			{
				// 对于Kylin操作系统，从特定文件中获取版本信息
				f := gf.NewFile("/etc/kylin-build")
				f.IsFile()
				if f.IsFiles {
					gc.RunShell("sed -n 2p /etc/kylin-build")
					info.Version = strings.Split(gc.Strings, " ")[1]
				} else {
					f.FileName = "/etc/kylin-release"
					f.IsFile()
					if f.IsFiles {
						gc.RunShell("cat ", f.FileName)
						sp := strings.Split(gc.Strings, " ")
						info.Version = sp[len(sp)-1]
						info.Version = strings.Replace(info.Version, "(", "", -1)
						info.Version = strings.Replace(info.Version, ")", "", -1)
					} else {
						info.Version = "获取失败"
					}
				}
			}
		case strings.ToLower("kali"):
			{
				// 对于Kali操作系统，获取版本信息
				gc.RunShell("sed -n 3p /etc/os-release")
				info.Version = strings.Split(gc.Strings, "=")[1]
				info.Version = strings.Replace(info.Version, "\"", "", 2)
			}
		case strings.ToLower("uos"):
			{
				// 对于UOS操作系统，获取版本信息
				gc.RunShell("grep ^Min /etc/os-version")
				info.Version = strings.Split(gc.Strings, "=")[1]
			}
		default:
			{
				// 对于其他Linux发行版，获取版本信息
				gc.RunShell("sed -n 3p /etc/os-release")
				info.Version = strings.Split(gc.Strings, "=")[1]
				info.Version = strings.Replace(info.Version, "\"", "", 2)
			}
		}

		// 获取Linux发行版的代号
		gc.RunShell("grep CODENAME /etc/os-release")
		info.CodeName = strings.Replace(gc.Strings, "\"", "", 2)
		info.CodeName = strings.Split(info.CodeName, "=")[1]
		info.CodeName = strings.Fields(info.CodeName)[0]

		// 检查执行命令过程中是否有错误
		// err = gc.Err

		// 清理版本号中的空白字符
		info.Version = strings.Fields(info.Version)[0]

		// 返回操作系统信息和可能的错误
		return info, nil
	} else {
		// 如果操作系统不是Linux，返回错误信息
		err = fmt.Errorf("仅支持Linux系统")
		logger.Warn(err.Error())
		return info, err
	}
}

// IsUos 检查当前操作系统是否为 "uos"。
// 返回值:
//   - bool: 如果操作系统是 "uos"，返回 true；否则返回 false。
func IsUos() bool {
	// 获取操作系统信息。
	oi, err := GetOsInfo()

	// 如果没有错误发生，表示成功获取了操作系统信息。
	if err == nil {
		// 检查操作系统名称是否为 "uos"（忽略大小写）。
		if strings.EqualFold(oi.Name, "uos") {
			return true
		}
	}

	// 如果操作系统名称不是 "uos" 或获取操作系统信息时有错误，则返回 false。
	return false
}
